In [1]:
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.subplots as sp
import plotly.graph_objects as go
from sklearn.feature_selection import mutual_info_regression

# Defina o símbolo do ativo que você deseja analisar
ativo = "AAPL"  # Exemplo: Apple Inc.

# Defina o intervalo de datas desejado
data_inicio = "2023-01-01"
data_fim = "2023-02-01"

# Baixe os dados do Yahoo Finance e renomeie o DataFrame para 'df'
df = yf.download(ativo,
                 start=data_inicio,
                 end=data_fim)
[*********************100%%**********************]  1 of 1 completed
In [2]:
# Exiba as primeiras linhas dos dados
display(df.head())
display(df.info())
Open High Low Close Adj Close Volume
Date
2023-01-03 130.279999 130.899994 124.169998 125.070000 124.538666 112117500
2023-01-04 126.889999 128.660004 125.080002 126.360001 125.823189 89113600
2023-01-05 127.129997 127.769997 124.760002 125.019997 124.488876 80962700
2023-01-06 126.010002 130.289993 124.889999 129.619995 129.069321 87754700
2023-01-09 130.470001 133.410004 129.889999 130.149994 129.597061 70790800
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 20 entries, 2023-01-03 to 2023-01-31
Data columns (total 6 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   Open       20 non-null     float64
 1   High       20 non-null     float64
 2   Low        20 non-null     float64
 3   Close      20 non-null     float64
 4   Adj Close  20 non-null     float64
 5   Volume     20 non-null     int64  
dtypes: float64(5), int64(1)
memory usage: 1.1 KB
None

#1 Tratamento dos dados

#1.1 Verificar o tipo de dados do índice (coluna de datas)

O dataset é identificado pela coluna da data, a fim de realizar análises temporais será necessário que esteja em formato datetime.

In [3]:
# Verificar o tipo de dados do índice (coluna de datas)
print(df.index.dtype)
datetime64[ns]

#1.2 Verificando a existência de dados nulos:

In [4]:
# Verificar valores nulos
valores_nulos = df.isnull().sum()
print(valores_nulos)
Open         0
High         0
Low          0
Close        0
Adj Close    0
Volume       0
dtype: int64

Conclusões:

#1.3 Verificando a existência de dados duplicados:

In [5]:
# Verificar se há linhas duplicadas
linhas_duplicadas = df[df.duplicated()]
print(linhas_duplicadas)
Empty DataFrame
Columns: [Open, High, Low, Close, Adj Close, Volume]
Index: []

Conclusões:

#1.4 Verificar se não há valores negativos utilizando o método .loc para selecionar as linhas onde os valores são negativos e, em seguida, visualizá-los:

In [6]:
linhas_com_valores_negativos = df[df['Open'] < 0]
print(linhas_com_valores_negativos)
Empty DataFrame
Columns: [Open, High, Low, Close, Adj Close, Volume]
Index: []

Conclusões:

#1.4 Verificar se não há valores com letras: Você pode usar o método .str.isnumeric() para verificar se os valores nas colunas são numéricos:

In [7]:
colunas_numericas = df.apply(pd.to_numeric, errors='coerce').notna().all()
print(colunas_numericas)
Open         True
High         True
Low          True
Close        True
Adj Close    True
Volume       True
dtype: bool

Conclusões:

#1.5 Verificação de Outliers:

In [8]:
import plotly.subplots as sp

# Definir tamanho personalizado para os gráficos
custom_size = (250, 200)  # Defina o tamanho desejado, por exemplo, (largura, altura)

# Criar uma figura com subplots
fig = sp.make_subplots(rows=1,
                       cols=6,
                       horizontal_spacing=0.1,
                       subplot_titles=['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'])

# Adicionar os boxplots à figura
fig.add_trace(px.box(df, y='Open').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=1)
fig.add_trace(px.box(df, y='High').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=2)
fig.add_trace(px.box(df, y='Low').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=3)
fig.add_trace(px.box(df, y='Close').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=4)
fig.add_trace(px.box(df, y='Adj Close').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=5)
fig.add_trace(px.box(df, y='Volume').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=6)

# Atualizar o layout da figura
fig.update_layout(title="Boxplots das Colunas Numéricas", showlegend=False)

# Exibir a figura
fig.show()

Conclusões:

#2 Análise Exploratória dos Dados:

Serão realizadas visualzações e resumos estatísticos em busca de entender melhor os dados.

#2.1 Estatísticas Descritivas:

In [9]:
# Realize uma análise básica dos dados

display(df.describe())
Open High Low Close Adj Close Volume
count 20.000000 20.000000 20.000000 20.000000 20.000000 2.000000e+01
mean 135.126000 137.271498 133.737001 135.778999 135.202166 7.218262e+07
std 5.921998 6.074987 6.448833 6.635885 6.607695 1.342587e+07
min 126.010002 127.769997 124.169998 125.019997 124.488876 5.410510e+07
25% 130.422501 132.872501 129.447498 130.584995 130.030220 6.398552e+07
50% 134.455002 136.769997 133.950005 135.240005 134.665459 6.956585e+07
75% 140.454998 143.200005 139.182499 142.027500 141.424126 8.040838e+07
max 144.960007 147.229996 143.080002 145.929993 145.310043 1.121175e+08

Conclusões:

#2.2 Distribuição dos dados:

In [10]:
import plotly.graph_objects as go

# Crie subplots com 2 linhas e 3 colunas
fig = sp.make_subplots(rows=2, cols=3)

# Parâmetros para o contorno das barras
marker_line = dict(
    color='black',
    width=1
)

# Opacidade das barras
opacity = 0.75

# Adicione os histogramas aos subplots com contornos nas barras
fig.add_trace(go.Histogram(
    x=df['Open'],
    name='Open',
    marker=dict(line=marker_line),
    opacity=opacity
), row=1, col=1)

fig.add_trace(go.Histogram(
    x=df['High'],
    name='High',
    marker=dict(line=marker_line),
    opacity=opacity
), row=1, col=2)

fig.add_trace(go.Histogram(
    x=df['Low'],
    name='Low',
    marker=dict(line=marker_line),
    opacity=opacity
), row=1, col=3)

fig.add_trace(go.Histogram(
    x=df['Close'],
    name='Close',
    marker=dict(line=marker_line),
    opacity=opacity
), row=2, col=1)

fig.add_trace(go.Histogram(
    x=df['Adj Close'],
    name='Adj Close',
    marker=dict(line=marker_line),
    opacity=opacity
), row=2, col=2)

fig.add_trace(go.Histogram(
    x=df['Volume'],
    name='Volume',
    marker=dict(line=marker_line),
    opacity=opacity
), row=2, col=3)

# Atualize os títulos e rótulos dos eixos
fig.update_xaxes(title_text='Open', row=1, col=1)
fig.update_xaxes(title_text='High', row=1, col=2)
fig.update_xaxes(title_text='Low', row=1, col=3)
fig.update_xaxes(title_text='Close', row=2, col=1)
fig.update_xaxes(title_text='Adj Close', row=2, col=2)
fig.update_xaxes(title_text='Volume', row=2, col=3)
fig.update_yaxes(title_text='Frequência')

# Atualize o layout do gráfico
fig.update_layout(title_text="Distribuição das Variáveis")

# Exiba o gráfico
fig.show()

Conclusões:

#2.3 Engenharia de Recursos (Feature Engineering):

In [11]:
# Calcular o retorno diário
df_retorno = df.copy()
df_retorno['Retorno Diário'] = df_retorno['Adj Close'].pct_change()
print("\nRetorno Diário:")
display(df_retorno['Retorno Diário'].head())

# Calcular o retorno acumulado
df_retorno['Retorno Acumulado'] = (1 + df_retorno['Retorno Diário']).cumprod()
print("\nRetorno Acumulado:")
display(df_retorno['Retorno Acumulado'].head())
Retorno Diário:
Date
2023-01-03         NaN
2023-01-04    0.010314
2023-01-05   -0.010605
2023-01-06    0.036794
2023-01-09    0.004089
Name: Retorno Diário, dtype: float64
Retorno Acumulado:
Date
2023-01-03         NaN
2023-01-04    1.010314
2023-01-05    0.999600
2023-01-06    1.036380
2023-01-09    1.040617
Name: Retorno Acumulado, dtype: float64

Conclusões:

#2.4 Gráficos de Linha

In [12]:
import plotly.graph_objects as go


# Criar um gráfico de linha com Plotly
fig = go.Figure()

# Adicionar preços de fechamento
fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Preço de Fechamento'))

# Atualizar layout
fig.update_layout(title="Gráfico de Linha Preço de Fechamento",
                  xaxis_title="Data",
                  yaxis_title="Preço",
                  showlegend=True)

# Exibir o gráfico
fig.show()
In [13]:
# Gráfico de Linhas para os Preços de Fechamento Ajustados:
fig = go.Figure()

fig.add_trace(go.Scatter(x=df.index,
                         y=df['Adj Close'],
                         mode='lines',
                         name='Preço de Fechamento Ajustado'))

fig.update_layout(title=f"Preço de Fechamento Ajustado de {ativo}",
                  xaxis_title='Data',
                  yaxis_title='Preço')

fig.show()

Conclusões:

#2. Análise de Correlações entre as variáveis:

Serão criados graficos Mapas de Calor que nos dão um valor numérico e uma representação gráfica da intensidade do mesmo e Gráficos de Dispersão.

In [14]:
# Selecionar as colunas desejadas
columns_to_include = ['Open', 'High', 'Low', 'Close', 'Adj Close']

# Criar um novo DataFrame com as colunas desejadas
df_subset = df[columns_to_include]

# Calcular a matriz de correlação
correlation_matrix = df_subset.corr()

# Criar um gráfico de mapa de calor (heatmap)
plt.figure(figsize=(5, 4))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=0.5)
plt.title("Matriz de Correlação")
plt.show()
In [15]:
import plotly.subplots as sp
import plotly.graph_objects as go

# Criar uma figura com subplots
fig = sp.make_subplots(rows=1, cols=5, subplot_titles=['Open vs. High',
                                                       'Open vs. Low',
                                                       'Open vs. Close',
                                                       'High vs. Low',
                                                       'High vs. Close'])

# Adicionar scatterplots aos subplots
fig.add_trace(go.Scatter(x=df['Open'], y=df['High'], mode='markers', name='Open vs. High'), row=1, col=1)
fig.add_trace(go.Scatter(x=df['Open'], y=df['Low'], mode='markers', name='Open vs. Low'), row=1, col=2)
fig.add_trace(go.Scatter(x=df['Open'], y=df['Close'], mode='markers', name='Open vs. Close'), row=1, col=3)
fig.add_trace(go.Scatter(x=df['High'], y=df['Low'], mode='markers', name='High vs. Low'), row=1, col=4)
fig.add_trace(go.Scatter(x=df['High'], y=df['Close'], mode='markers', name='High vs. Close'), row=1, col=5)

# Atualizar layout
fig.update_layout(title="Scatterplots das Variáveis",
                  xaxis_title="X-Axis",
                  yaxis_title="Y-Axis",
                  showlegend=True)  # Mostrar legenda

# Exibir a figura
fig.show()

Conclusões:

Correlação Linear Positiva....

#2. Extra - Gráfico de Velas (Candlestick) com Plotly:

Será criado um gráfico de Candlestick, que é amplamente utilizado no mercado financeiro. Cada candle(vela) representa toda a movimentação de preço de um dia de pregão e traz as informações do preço de abertura, fechamento, máxima e mínima daquele dia. Uma média móvel aritimética (SMA) de 7 períodos aplicada ao preço de fechamento foi calculada para melhor entendermos qual o preço médio do fechamento e a tendência de preços do ativo nesse período analisado.

In [16]:
# Calcular a média móvel aritmética (SMA)
window = 7  # Janela da média móvel
df['SMA'] = df['Close'].rolling(window=window).mean()

# Criar o gráfico de velas (candlestick) com a média móvel
fig = go.Figure()

# Adicionar o gráfico de velas
fig.add_trace(go.Candlestick(x=df.index,
                open=df['Open'],
                high=df['High'],
                low=df['Low'],
                close=df['Close'], name='Candlestick'))

# Adicionar a média móvel como um segundo eixo
fig.add_trace(go.Scatter(x=df.index,
                         y=df['SMA'],
                         mode='lines',
                         line=dict(color='blue'),
                         name=f'SMA-{window}'))

# Atualizar layout
fig.update_layout(title="Gráfico de Velas (Candlestick) com Média Móvel",
                  xaxis_title="Data",
                  yaxis_title="Preço",
                  showlegend=True)  # Mostrar legenda

# Criar um segundo eixo y para a média móvel
fig.update_layout(yaxis2=dict(title=f'SMA-{window}', overlaying='y', side='right'))

# Exibir o gráfico
fig.show()
  1. Uma análise de tabelas de contingência ou de agregações. (faltando)
In [ ]:
 
  1. Uma análise de informação mútua, emprego de atributos derivados ou teste de interdependência. (Incompleto)
In [17]:
from sklearn.feature_selection import mutual_info_regression
import numpy as np

# Defina as variáveis independentes (preços) e a variável dependente (volume)
prices = df[['Open', 'High', 'Low', 'Close']].values
volume = df['Volume'].values

# Calcule a informação mútua entre os preços e o volume
mi_scores = mutual_info_regression(prices, volume)
mi_scores
Out[17]:
array([0.09328007, 0.        , 0.05589206, 0.11811123])

Conclusões:

Para a variável 'Open': O valor de informação mútua é aproximadamente 0.0933. Isso indica uma dependência positiva (embora não muito forte) entre a variável 'Open' e o volume de negociação. Significa que há alguma relação entre o preço de abertura e o volume, mas essa relação não é muito forte.

Para a variável 'High': O valor de informação mútua é 0. Isso sugere que não há uma dependência linear entre a variável 'High' e o volume de negociação. A informação mútua 0 indica que essas variáveis não têm uma relação linear significativa.

Para a variável 'Low': O valor de informação mútua é aproximadamente 0.0559. Isso indica uma dependência positiva, mas não muito forte, entre a variável 'Low' e o volume de negociação. Assim como no caso da variável 'Open', há alguma relação entre o preço mínimo e o volume, mas não é muito forte.

Para a variável 'Close': O valor de informação mútua é aproximadamente 0.1181. Isso indica uma dependência positiva entre a variável 'Close' (preço de fechamento) e o volume de negociação. Essa dependência é um pouco mais forte do que a observada nas variáveis 'Open' e 'Low'.

O valor 0. (zero) para a variável 'High' significa que, de acordo com a análise de informação mútua, não há uma relação linear significativa entre o preço mais alto ('High') e o volume de negociação. Pode ser o caso de que essas variáveis não estão linearmente relacionadas ou que a relação é muito fraca para ser detectada pela métrica de informação mútua.

In [ ]: